package com.lobov.utils;

import org.apache.hadoop.io.Text;

import com.lobov.containers.MultiPairYale;
import com.lobov.entities.Matrix;
import com.lobov.entities.yale.MatrixYale;
import com.lobov.entities.yale.SnipYale;
import com.lobov.entities.yale.SparseVector;

public class Transformer {

	public static Matrix transposeMatrix(Matrix mHor) {
		Matrix mVert = new Matrix(mHor.getYlength(), mHor.getXlength());
		int length = mHor.getValues().length;
		double[] oldVals = mHor.getValues();
		double[] newVals = new double[length];
		int[] oldXs = mHor.getXs();
		int[] oldYs = mHor.getYs();
		int[] newXs = new int[length];
		int[] newYs = new int[length];
		int num = 0;
		for (int x = 0; x < mHor.getXlength(); x++) {
			for (int y = 0; y < mHor.getYlength(); y++) {
				newVals[num] = oldVals[x + y * mHor.getXlength()];
				newXs[num] = oldXs[x + y * mHor.getXlength()];
				newYs[num] = oldYs[x + y * mHor.getXlength()];
				num++;
			}
		}
		mVert.setValues(newVals);
		mVert.setXs(newXs);
		mVert.setYs(newYs);
		return mVert;
	}

	public static MatrixYale transposeMatrixYale(MatrixYale oldMatrix)
			throws Exception {
		if (oldMatrix.isCompressed()) {
			throw new Exception("Сжатую матрицу нельзя транспонировать");
		}
		int oldColumns = oldMatrix.getXlength();
		int oldRows = oldMatrix.getYlength();
		MatrixYale newMatrix = copyTemplateTransparentMatrixYale(oldMatrix);
		for (int x = 1; x <= oldColumns; x++) {
			for (int y = 1; y <= oldRows; y++) {
				newMatrix.setElementByXY(y, x, oldMatrix.getElementByXY(x, y));
			}
		}
		return newMatrix;
	}

	private static MatrixYale copyTemplateTransparentMatrixYale(
			MatrixYale matrix) {

		int xLength = matrix.getYlength();
		int yLength = matrix.getXlength();

		SparseVector[] newEmtyVectors = new SparseVector[yLength];
		for (int i = 0; i < yLength; i++) {
			newEmtyVectors[i] = new SparseVector(xLength, i,
					new double[xLength], null, false);
		}
		return new MatrixYale(newEmtyVectors, false);
	}

	public static MatrixYale matrixYaleFromText(String string) {
		return matrixYaleFromText(new Text(string));
	}

	public static MatrixYale matrixYaleFromText(Text text) {
		String src = text.toString();

		String[] strVectors = src.split("#");
		SparseVector[] vectors = new SparseVector[strVectors.length];
		boolean compressed = false;

		for (int i = 0; i < strVectors.length; i++) {
			strVectors[i] = strVectors[i].trim();
			int yPosition = i;

			String[] strVals = strVectors[i].split(" ");
			int xLength = strVals.length;

			double[] values = new double[strVals.length];
			int xs[] = new int[strVals.length];

			for (int p = 0; p < strVals.length; p++) {
				values[p] = Double.parseDouble(strVals[p]);
				xs[p] = p;
			}

			SparseVector spv = new SparseVector(xLength, yPosition, values, xs,
					compressed);

			vectors[i] = spv;
		}

		return new MatrixYale(vectors, compressed);
	}

	public static SnipYale snipYaleFromText(String string) {
		return snipYaleFromText(new Text(string));
	}

	public static SnipYale snipYaleFromText(Text text) {

		String src = text.toString();

		String[] splits = src.split("@@@");

		int orderNumInContainer = Integer.parseInt(splits[0]);

		String[] strVectors = splits[1].split("#");
		SparseVector[] vectors = new SparseVector[strVectors.length];
		boolean compressed = false;
		boolean flipped = false;

		for (int i = 0; i < strVectors.length; i++) {
			strVectors[i] = strVectors[i].trim();
			int yPosition = i;

			String[] strVals = strVectors[i].split(" ");
			int xLength = strVals.length;

			double[] values = new double[strVals.length];
			int xs[] = new int[strVals.length];

			for (int p = 0; p < strVals.length; p++) {
				values[p] = Double.parseDouble(strVals[p]);
				xs[p] = p;
			}

			SparseVector spv = new SparseVector(xLength, yPosition, values, xs,
					compressed);

			vectors[i] = spv;
		}

		return new SnipYale(vectors, compressed, orderNumInContainer);
	}

	public static MultiPairYale getMatrixAndSnipPairFromText(Text text) {
		String src = text.toString();
		String[] entities = src.split("####");
		String matrixStr = entities[0];
		String snipStr = entities[1];
		MatrixYale matrix = matrixYaleFromText(matrixStr);
		SnipYale snip = snipYaleFromText(snipStr);
		return new MultiPairYale(matrix, snip);
	}

}
